#include <iostream>
#include <cmath>
#include "colormap.hpp"


using namespace std;


Colormap::Colormap(int max_iter):
    max_iter(max_iter)
{
}


void Colormap::gen_color(int iter_num, const complex<double> &pos, 
			 float &r, float &g, float &b) const
{
    r = g = b = 0;
}


ColormapRed::ColormapRed(int max_iter):
    Colormap(max_iter)
{
}


void ColormapRed::gen_color(int iter_num, const complex<double> &pos, 
			    float &r, float &g, float &b) const
{
    r = ((0+7*iter_num)%max_iter)*1.0/max_iter;
    g = (((iter_num/4))%max_iter)/max_iter;
    b = (((iter_num/4))%max_iter)/max_iter;
}


ColormapZebra::ColormapZebra(int max_iter):
    Colormap(max_iter)
{
}


void ColormapZebra::gen_color(int iter_num, const complex<double> &pos, 
			      float &r, float &g, float &b) const
{
    r = g = b = iter_num % 2;
}


ColormapMndClassic::ColormapMndClassic(int iter_num):
    Colormap(iter_num)
{
}


void ColormapMndClassic::gen_color(int iter_num, const complex<double> &pos, 
			      float &r, float &g, float &b) const
{
    if (iter_num < max_iter - 1)
	r = g = b = 1.0;
    else
	r = g = b = 0.0;
}


ColormapLevel::ColormapLevel(int max_iter):
    Colormap(max_iter)
{
}


void ColormapLevel::gen_color(int iter_num, const complex<double> &pos, 
			 float &r, float &g, float &b) const
{
    r = g = b = iter_num*1.0 / max_iter;
}


ColormapLevelLog::ColormapLevelLog(int max_iter):
    Colormap(max_iter)
{
}


void ColormapLevelLog::gen_color(int iter_num, const complex<double> &pos, 
				 float &r, float &g, float &b) const
{
    double maxlog = log(max_iter);
    r = g = b = log(iter_num) / maxlog;
}


ColormapNewton3::ColormapNewton3(int max_iter):
    Colormap(max_iter)
{
    _roots[0] = complex<double>(1, 0);
    _roots[1] = complex<double>(-0.5, sqrt(3)/2);
    _roots[2] = complex<double>(-0.5, -sqrt(3)/2);
}


void ColormapNewton3::gen_color(int iter_num, const complex<double> &pos, 
				float &r, float &g, float &b) const
{
    int n = 0;
    double err = 100500;
    
    for (int i = 0; i < 3; i++) {
	double t = abs(pos-_roots[i]);
	if (t < err) {
	    err = t;
	    n = i;
	}
    }
    switch (n) {
    case 0:
	r = 1.0;
	g = b = 0.0;
	break;
    case 1:
	g = 1.0;
	r = b = 0.0;
	break;
    case 2:
	b = 1.0;
	r = g = 0.0;
	break;
    }
}


ColormapNewton3Lvl::ColormapNewton3Lvl(int max_iter):
    Colormap(max_iter)
{
    _roots[0] = complex<double>(1, 0);
    _roots[1] = complex<double>(-0.5, sqrt(3)/2);
    _roots[2] = complex<double>(-0.5, -sqrt(3)/2);
}


void ColormapNewton3Lvl::gen_color(int iter_num, const complex<double> &pos, 
				   float &r, float &g, float &b) const
{
    int n = 0;
    double err = 100500;
    
    for (int i = 0; i < 3; i++) {
	double t = abs(pos-_roots[i]);
	if (t < err) {
	    err = t;
	    n = i;
	}
    }
    switch (n) {
    case 0:
	r = iter_num*1.0/max_iter;
	g = b = 0.0;
	break;
    case 1:
	g = iter_num*1.0/max_iter;
	r = b = 0.0;
	break;
    case 2:
	b = iter_num*1.0/max_iter;
	r = g = 0.0;
	break;
    }
}


ColormapNewton3LvlLog::ColormapNewton3LvlLog(int max_iter):
    Colormap(max_iter)
{
    _roots[0] = complex<double>(1, 0);
    _roots[1] = complex<double>(-0.5, sqrt(3)/2);
    _roots[2] = complex<double>(-0.5, -sqrt(3)/2);
}


void ColormapNewton3LvlLog::gen_color(int iter_num, const complex<double> &pos, 
				      float &r, float &g, float &b) const
{
    int n = 0;
    double err = 100500;
    
    for (int i = 0; i < 3; i++) {
	double t = abs(pos-_roots[i]);
	if (t < err) {
	    err = t;
	    n = i;
	}
    }
    double maxlog = log(max_iter);
    switch (n) {
    case 0:
	r = log(iter_num)/maxlog;
	g = b = 0.0;
	break;
    case 1:
	g = log(iter_num)/maxlog;
	r = b = 0.0;
	break;
    case 2:
	b = log(iter_num)/maxlog;
	r = g = 0.0;
	break;
    }
}
